#ifndef ARCHIVOTERMINOS_H
#define ARCHIVOTERMINOS_H

#include "Archivo.h"
#include "stdint.h"

class ArchivoTerminos: public Archivo {
private:
    const char* filename;
    string terminoAnterior;

    unsigned int length;

public:
    ArchivoTerminos(const char* filename):Archivo(filename) {
        this->filename = filename;
        this->terminoAnterior = string("");

        this->clear();
        this->seekg(0, ios::end);

        this->length = this->tellg();
        this->clear();
        this->seekg(0, ios::beg);
    }

    void write(string str) {
        unsigned char rep = (unsigned char) 0;
        unsigned char dist = (unsigned char) 0;

        short int size = this->terminoAnterior.size() - str.size();
        if (size > 0)
            size = str.size();
        else
            size = this->terminoAnterior.size();

        for (int i = 0; i < size; i++) {
            if (str.at(i) == this->terminoAnterior.at(i))
                rep++;
            else
                break;
        }

        dist = (unsigned char) str.size() - rep;

        Archivo::write((char*) &rep, sizeof(unsigned char));
        Archivo::write((char*) &dist, sizeof(unsigned char));

        char* ch = new char[dist + 1];

        if (this->terminoAnterior.empty())
            strcpy(ch, str.c_str());
        else
            strcpy(ch, str.substr(rep).c_str());
        this->terminoAnterior = str;

        Archivo::write((char*) ch, dist);
        delete []ch;

        this->length = this->tellp();
    }

    string read() {
        if (this->length == ((unsigned int) this->tellg())) {
            this->terminoAnterior.clear();
            return this->terminoAnterior;
        }

        unsigned char rep;
        unsigned char dist;

        Archivo::read((char*) &rep, sizeof(unsigned char));
        Archivo::read((char*) &dist, sizeof(unsigned char));

        char* buf = new char[dist + 1];
        Archivo::read((char*) buf, dist);
        buf[dist] = '\0';

        string str = string(buf);
        delete []buf;

        this->terminoAnterior = this->terminoAnterior.substr(0, rep).append(str);
        return this->terminoAnterior;
    }

    void destroy() {
        this->close();
        remove (this->filename);
    }

    ~ArchivoTerminos() {
        this->close();
    }

};

#endif // ARCHIVOTERMINOS_H
